from django.core.paginator              import Paginator,InvalidPage
from django.http                        import HttpResponse,HttpResponseForbidden
from django.template                    import RequestContext
from sitepal.sitemenu.actions.actions   import ACTION_READ_OBJECT
from sitepal.sitemenu.actions.base_view import BaseView

class ListView(BaseView):
    def __init__(self,rows,paginate_by=None,page=None,allow_empty=True,**kwargs):
        assert callable(rows) or isinstance(rows,(list,tuple))
        assert page is None or callable(page) or isinstance(page,(int,long))
        assert paginate_by is None or callable(paginate_by) or isinstance(paginate_by,(int,long))
        BaseView.__init__(self,**kwargs)
        if not self._template_object_name.endswith('_list'):
            self._template_object_name = "{0}_list".format(self._template_object_name)
        self._paginate_by = paginate_by
        self._page        = page
        self._allow_empty = allow_empty
        self._rows        = rows

    @property
    def page(self):
        if callable(self._page):
            return self._page()
        return self._page

    @property
    def paginate_by(self):
        if callable(self._paginate_by):
            return self._paginate_by()
        return self._paginate_by

    def get_rows(self,request):
        from sitepal.siteface.actions.generic import Http403

        if not self.has_perm(ACTION_READ_OBJECT,request.user):
            raise Http403
        if callable(self._rows):
            return self._rows(self,request)
        raise self._rows

    def get_page_index(self,request,paginator):
        session_key = "{0}:page_index".format(request.path)
        page        = self.page
        if not page:
            if 'page' in request.GET:
                page = request.GET['page']
            elif hasattr(request,'session') and session_key in request.session:
                page = request.session[session_key]
            else:
                page = 1
        try:
            if hasattr(request,'session'):
                request.session[session_key] = int(page)
            return int(page)
        except ValueError:
            if page == 'last':
                if hasattr(request,'session'):
                    request.session[session_key] = paginator.num_pages
                return paginator.num_pages
            else:
                if hasattr(request,'session'):
                    request.session[session_key] = 1
                return 1

    def get_context(self,request,template_obj,paginator=None,page_obj=None):
        context = BaseView.get_context(self,request,template_obj)
        context['paginator'] = paginator
        context['page_obj']  = page_obj
        if page_obj:
            context['is_paginated'] = page_obj.has_other_pages()
        else:
            context['is_paginated'] = False
        return context

    def handle_get(self,request,**kwargs):
        rows = self.get_rows(request)
        if isinstance(rows,HttpResponse):
            return rows
        if self._paginate_by:
            try:
                paginator = Paginator(rows,self.paginate_by,
                                      allow_empty_first_page=self._allow_empty)
                page_obj  = paginator.page(self.get_page_index(request,paginator))
                context   = self.get_context(request,page_obj.object_list,paginator,page_obj)
                return self.response(request,context)
            except InvalidPage:
                return HttpResponseNotFound
        else:
            if not self._allow_empty and len(rows) == 0:
                return HttpResponseNotFound
            context = self.get_context(request,rows)
            return self.response(request,context)

